package com.bac.rentmap.ad.flat.crawler.localaddress;

import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.util.StringUtils;

import com.bac.rentmap.ad.flat.LocalAddress;
import com.bac.rentmap.ad.flat.LocalAddressPrefix;

public class SentenceLocalAddressParser implements LocalAddressParser {
    private static final Logger log = Logger
            .getLogger(SentenceLocalAddressParser.class.getName());

    private Pattern addressPattern;
    private Pattern addressWithBuildingPattern;

    public SentenceLocalAddressParser() {
        List<String> prefixes = LocalAddressPrefix.getSynonymPatterns();
        String prefixesRegex = StringUtils.collectionToDelimitedString(
                prefixes, "|");
        addressPattern = Pattern
                .compile(
                        ".*("
                                + prefixesRegex
                                + ")[\\.\\s]\\s*((\\p{L}+)(?:[\\p{L}\\s]*\\p{L})?)(?:$|\\s|\\(|\\.|,)",
                        Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
        log.info("Pattern: " + addressPattern);

        addressWithBuildingPattern = Pattern
                .compile(
                        ".*("
                                + prefixesRegex
                                + ")[\\.\\s]\\s*((\\p{L}+)(?:[\\p{L}\\s]*\\p{L})?)\\s*,?\\s*(?:д\\.)?(\\d+)(?:$|\\s|\\(|\\.|,)",
                        Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
        log
                .info("Address with building Pattern: "
                        + addressWithBuildingPattern);
    }

    public LocalAddress parse(String string) {
        LocalAddressPrefix prefix = null;
        String street = null;
        Integer building = null;
        Matcher matcher = addressWithBuildingPattern.matcher(string);
        boolean matchFound = matcher.find();
        if (matchFound) {
            String prefixString = matcher.group(1);
            if (prefixString != null) {
                prefix = LocalAddressPrefix.valueOfSynonym(prefixString);
            }
            String buildingString = matcher.group(4);
            building = Integer.valueOf(buildingString);
            street = matcher.group(2);
        } else {
            log.fine("Searching address without building");
            matcher = addressPattern.matcher(string);
            matchFound = matcher.find();
            if (matchFound) {
                String prefixString = matcher.group(1);
                if (prefixString != null) {
                    prefix = LocalAddressPrefix.valueOfSynonym(prefixString);
                }
                street = matcher.group(3);
            } else {
                throw new IllegalArgumentException("Can't parse address from "
                        + string);
            }
        }
        if (street.length() < 3) {
            throw new IllegalArgumentException("Too short street " + string);
        }
        LocalAddress res = new LocalAddress(prefix, street, building);
        log.info("Parsed '" + string + "' to " + res);
        return res;
    }

}
